/***********************************************************************
 * Module:  BaseMetaData.java
 * Author:  juny
 * Created: 2006年7月13日 13:44:38
 * Purpose: 所有元数据模板变量的基类
 ***********************************************************************/

package com.powerunion.datacollection.report.excelreport.base;

import java.util.Date;
import java.util.List;

import com.powerunion.datacollection.report.excelreport.base.element.Property;
import com.powerunion.datacollection.report.excelreport.util.AnalyseTempletTool;
import com.powerunion.datacollection.report.excelreport.util.HelpTools;

import jxl.CellType;
import jxl.format.CellFormat;
import jxl.write.DateTime;
import jxl.write.Formula;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.WritableCell;
import jxl.write.WritableCellFeatures;

/**
 * 元素类模板变量基类
 * @author juny
 */
public abstract class BaseField extends BaseElement {
    
    /**
     * @param container 包含本模板变量得容器
     */
    public BaseField(ITempletContainer container) {
        super(container);
    }
    
    /**
     * 拷贝默认的单元格。
     * @param param
     * @param value
     * @return
     */
    protected WritableCell copyDefaultCell(Parameter param, Object value){
        WritableCell retCell = param.wc.copyTo(param.destCol, param.destRow);
        if (retCell.getType() == CellType.LABEL){
            Label l = (Label) retCell;
            l.setString(value.toString());
        }
        return retCell;
    }
    
    /**
     * 根据传入单元格的类型，生成该类型的新单元格，并从传入的模板单元格中
     * 拷贝单元格的属性信息到新的单元格中。
     * @param cell		模板单元格，新生成的单元格会复制模板单元格的所有属性。
     * @param value		新单元格中需放入的值
     * @param cellType 要生成的单元格的类型
     * @param destCol	新生成单元格的列
     * @param destRow	新生成单元格的行
     * @return		返回新生成的单元格。
     */
    protected WritableCell copyCellByType(WritableCell cell, Object value, byte cellType,
            int destCol, int destRow) {
    	if(null == cell || null == value){
    		return null;
    	}
    	
    	CellFormat cellformat = cell.getCellFormat();
    	WritableCell retCell = null;
    	
    	switch(cellType){
    		case CELL_TYPE_DATE:
    			DateTime dt = null;
                if (null != cellformat) {
                    dt = new DateTime(destCol, destRow, (Date) value, cellformat);
                } else {
                    dt = new DateTime(destCol, destRow, (Date) value);
                }
                retCell = dt;
    			break;
    			
    		case CELL_TYPE_NUMBER:
    			Number number = null;
                if (null != cellformat) {
                    number = new Number(destCol, destRow, Double.parseDouble(value
                            .toString()), cellformat);
                } else {
                    number = new Number(destCol, destRow, Double.parseDouble(value
                            .toString()));
                }
                retCell = number;
    			break;
    			
    		case CELL_TYPE_LABEL:
                Label label = null;
                if(null != cellformat){
                    label = new Label(destCol, destRow, value.toString(), cellformat);
                }else{
                    label = new Label(destCol, destRow, value.toString());
                }
                retCell = label;
    			break;
    			
    		case CELL_TYPE_FORMULATE:
    			Formula f = null;
    			if(null != cellformat){
    				f = new Formula(destCol, destRow, value.toString(),cellformat);
    			}else{
    				f = new Formula(destCol, destRow, value.toString());
    			}
    			retCell = f;
    			break;
    			
    		default:
    			
    	}
    	
    	if (null != retCell) {
            WritableCellFeatures wcf = cell.getWritableCellFeatures();
            if (null != wcf) {
            	WritableCellFeatures newWcf = new WritableCellFeatures(wcf);
            	retCell.setCellFeatures(newWcf);
            }
        }

        return retCell;
    }
    
    /**
     * 具体写数据实现方法，继承类重载该函数来实现具体的数据写入操作。<br>
     * 注意：之所以这样设计是为了防止所有继承至BaseField的类都去重载write(),
     * 因为如果直接重载write那么重载的客户write函数必须调用super.write()
     * 来执行如触发监听字段等一些写数据过程中必须触发的额外动作，
     * 如果重载writeImple那么客户程序只需关心自己writeImpl()的实现，而无需
     * 关心在执行完writeImpl()之后还需要去通知其监听域字段等细节。这种实现更安全。<br>
     * @param 
     * @return true :写值成功,通知监听器; false:写值失败;
     */
    public abstract boolean writeImpl(Parameter param) throws Exception;
    
    /**
     * @see net.excel.report.base.IElementWriter#write()
     */
    public final boolean write(Parameter param) throws Exception {
        beforeWriteProcess(param);
        if(writeImpl(param)){
            processProperty(param);
            notifyFieldValueListener(param);      
            afterWriteProcess(param);
            return true;
        }
        afterWriteProcess(param);
        return false;
    }
    
    protected void beforeWriteProcess(Parameter param){
        ;
    }
    
    /**
     * 生成某个报表单元格后处理函数
     * @param param
     */
    protected void afterWriteProcess(Parameter param){
        return;
    }
    
    /**
     * 处理模板变量属性
     * @param param
     */
    protected void processProperty(Parameter param){
        Property p = this.getProperty();
        if(null == p) return;
        
        BaseFieldProperty p1 = (BaseFieldProperty)p;
        //处理属性ignorSaveField
        p1.processIgnoreSameField(param);
    }
    
    /*
     * (non-Javadoc)
     * @see net.excel.report.base.BaseElement#getPropertyInstance()
     */
    protected Property getPropertyInstance(){
        return new BaseFieldProperty();
    }
    
    /**
     * 计算字段监听器处理函数。
     * @param param
     */
    private void notifyFieldValueListener(Parameter param){
        List fieldValueListeners = getFieldValueListeners();
        if(null != fieldValueListeners ){
            int col = 0;
            int row = 0;
            
            String content = "";
            if(null != param.wc){
                col = param.wc.getColumn();
                row = param.wc.getRow();
                content = param.wc.getContents();
            }
            
            for(int i=0; i<fieldValueListeners.size(); i++){
                ((IFieldValueListener)fieldValueListeners.get(i)).setValue(
                        this.getName(),
                        content,
                        col,
                        row
                );
            }
        }
    }
    
    /**
     * 获取某个字符串内容中声明的模板元素对象,如果有则返回包含所有这些元素声明的列表.
     * @param content
     * @return
     */
    protected List getDeclareFields(StringBuffer content){
        List fields = AnalyseTempletTool.getAllSubInfo(
                content.toString(),
                AnalyseTempletTool.REGEX_FIELD_TEMPLET);
        String field = null;
        //去掉重复的字段名称
        for(int i=0; i<fields.size(); i++){
            field = (String)fields.get(i);
            for(int j=i+1; j<fields.size(); j++){
                if(field.equals((String)fields.get(j))){
                    fields.remove(j);
                }
            }
        }
        return fields;
    }
    
    protected final static byte CELL_TYPE_FORMULATE = 3;
    protected final static byte CELL_TYPE_LABEL = 2;
    protected final static byte CELL_TYPE_DATE = 1;
    protected final static byte CELL_TYPE_NUMBER = 0;
    
    protected class BaseFieldProperty extends Property{
        protected void processIgnoreSameField(Parameter param){
            if(this.isIgnoreSaveValue()){
                String content = param.wc.getContents();
                if(null != strOldContents && strOldContents.equals(content)){
                    if(param.wc instanceof Label){
                        ((Label)param.wc).setString("");
                    }else{
                        param.wc = copyCellByType(param.wc, 
                                            "",
                                            CELL_TYPE_LABEL,
                                            param.wc.getColumn(),
                                            param.wc.getRow()
                                            );
                    }
                }else{
                    strOldContents = content;
                }
            }
        }
        
        protected boolean isIgnoreSaveValue(){
            String propertyValue = this.getPropertyValue(AnalyseTempletTool.FIELD_PROPERTY_IGNORESAMEVALUE);
            if(HelpTools.notEmpty(propertyValue) && propertyValue.equals("true")){
                return true;
            }
            return false;
        }
        private String strOldContents;
    }
}